#include <iostream>
using namespace std;

class EmployType 
{
public:
	virtual ~EmployType() {}
	virtual void paid()=0;
};

class Hourly: public EmployType 
{
public:
	void paid() 
	{
		cout << "pay the hourly salary" << endl;
	}
};

class Salaried: public EmployType 
{
public:
	void paid() 
	{
		cout << "pay the formal salary" << endl;
	}
};

class Employee 
{
private:
	EmployType* employType;
public:
	void setEmployType(EmployType* employType) 
	{
		this->employType = employType;
	}
	Employee(EmployType* employType) 
	{
		setEmployType(employType);
	}
	void salary() 
	{
		this->employType->paid();
	}
};

class Manager: public Employee 
{
public:
	Manager(EmployType* employType):Employee(employType) 
	{
		cout << ">>> This is an manager:" << endl;
	}
};

class Technican: public Employee 
{
public:
	Technican(EmployType* employType):Employee(employType) 
	{
		cout << ">>> This is a technican:" << endl;
	}
};

class Salesman: public Employee 
{
public:
	Salesman(EmployType* employType):Employee(employType) 
	{
		cout << ">>> This is a salesman:" << endl;
	}
};

class EmployTypeFactory
{
private:
    EmployTypeFactory();
public:
    static EmployTypeFactory* getInstance()
    {
        static EmployTypeFactory* instance;
        return instance;
    }
    EmployType* create(string name)
    {
        if (name=="hourly") return new Hourly();
        else if (name=="salaried") return new Salaried();
        else return NULL;
    }
};

class EmployeeFactory
{
private:
    EmployeeFactory();
public:
    static EmployeeFactory* getInstance()
    {
        static EmployeeFactory* instance;
        return instance;
    }
    Employee* create(string name)
    {
        EmployTypeFactory* employTypeFactory = EmployTypeFactory::getInstance();
        EmployType* hourly = employTypeFactory->create("hourly");
        EmployType* salaried = employTypeFactory->create("salaried");
        
        if (name=="hourlyManager") return new Manager(hourly);
        else if (name=="salariedManager") return new Manager(salaried);
        else if (name=="hourlyTechnican") return new Technican(hourly);
        else if (name=="salariedTechnican") return new Technican(salaried);
        else if (name=="hourlySalesman") return new Salesman(hourly);
        else if (name=="salariedSalesman") return new Salesman(salaried);
        else return NULL;
    }
};

int main() 
{
	EmployeeFactory* factory = EmployeeFactory::getInstance();
	Employee* hourlyManager = factory->create("hourlyManager");
	hourlyManager->salary();
	Employee* salariedManager = factory->create("salariedManager");
	salariedManager->salary();
	Employee* hourlyTechnican = factory->create("hourlyTechnican");
	hourlyTechnican->salary();
	Employee* salariedTechnican = factory->create("salariedTechnican");
	salariedTechnican->salary();
	Employee* hourlySalesman = factory->create("hourlySalesman");
	hourlySalesman->salary();
	Employee* salariedSalesman = factory->create("salariedSalesman");
	salariedSalesman->salary();
	return 0;
}
